---
title: Android Kotlin Quickstart
sidebar_label: Android Kotlin
description: "Add Convex to an Android Kotlin project"
hide_table_of_contents: true
sidebar_position: 600
---

Learn how to query data from Convex in a Android Kotlin project.

This quickstart assumes that you have Android Studio, node and npm installed. If
you don’t have those tools, take time to install them first.

<StepByStep>
  <Step title="Create a new Android app in Android Studio">
    Choose the following options in the wizard.

    ```
    1. Choose the "Empty Activity" template
    2. Name it "Convex Quickstart"
    3. Choose min SDK as 26
    4. Choose Kotlin as the Gradle DSL
    ```

  </Step>

  <Step title="Configure the AndroidManifest">
    Add the following to your `AndroidManifest.xml`.

    ```xml
    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools">
        // highlight-next-line
        <uses-permission android:name="android.permission.INTERNET"/>
        <application>
            <!-- ... existing application contents -->
        </application>
    </manifest>
    ```

  </Step>

  <Step title="Configure your dependencies">
    Add the following entries to the `:app` `build.gradle.kts` file (ignore IDE
    suggestion to move them to version catalog for now, if present).
    
    Ensure that you sync Gradle when all of the above is complete (Android
    Studio should prompt you to do so).

    ```kotlin
    plugins {
        // ... existing plugins
        // highlight-next-line
        kotlin("plugin.serialization") version "1.9.0"
    }

    dependencies {
        // ... existing dependencies
        // highlight-next-line
        implementation("dev.convex:android-convexmobile:0.4.1@aar") {
            // highlight-next-line
            isTransitive = true
        // highlight-next-line
        }
        // highlight-next-line
        implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.3")
    }
    ```

  </Step>

  <Step title="Install the Convex Backend">
    Open a terminal in your Android Studio instance and install the Convex 
    client and server library.

    ```bash
    npm init -y
    npm install convex
    ```

  </Step>

  <Step title="Start Convex">
    Start a Convex dev deployment. Follow the command line instructions.

    ```bash
    npx convex dev
    ```

  </Step>

  <Step title="Create a sample data for your database">
    Create a new `sampleData.jsonl` file with these contents.

    ```json
    {"text": "Buy groceries", "isCompleted": true}
    {"text": "Go for a swim", "isCompleted": true}
    {"text": "Integrate Convex", "isCompleted": false}
    ```

  </Step>

  <Step title="Add the sample data to your database">
    Open another terminal tab and run.

    ```bash
    npx convex import --table tasks sampleData.jsonl
    ```

  </Step>

  <Step title="Expose a database query">
    Create a `tasks.ts` file in your `convex/` directory with the following 
    contents.

    ```tsx
    import { query } from "./_generated/server";

    export const get = query({
      args: {},
      handler: async (ctx) => {
        return await ctx.db.query("tasks").collect();
      },
    });
    ```

  </Step>

  <Step title="Create a data class">
    Add a new `data class` to your `MainActivity` to support the task data 
    defined above. Import whatever it asks you to.

    ```kotlin
    @Serializable
    data class Task(val text: String, val isCompleted: Boolean)
    ```

  </Step>

  <Step title="Create your UI">
    Delete the template `@Composable` functions that Android Studio created and
    add a new one to display data from your Convex deployment. Again, import
    whatever it asks you to.

    ```kotlin
    @Composable
    fun Tasks(client: ConvexClient, modifier: Modifier = Modifier) {
        var tasks: List<Task> by remember { mutableStateOf(listOf()) }
        LaunchedEffect(key1 = "launch") {
            client.subscribe<List<Task>>("tasks:get").collect { result ->
                result.onSuccess { remoteTasks ->
                    tasks = remoteTasks
                }
            }
        }
        LazyColumn(
            modifier = modifier
        ) {
            items(tasks) { task ->
                Text(text = "Text: ${task.text}, Completed?: ${task.isCompleted}")
            }
        }
    }
    ```

  </Step>

  <Step title="Connect the app to your backend">
    1. Get the deployment URL of your dev server with
        `cat .env.local | grep CONVEX_URL`
    2. Update the `onCreate` method in your `MainActivity.kt` to look like

    ```kotlin
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        setContent {
            ConvexQuickstartTheme {
                Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
                    // highlight-next-line
                    Tasks(
                        // highlight-next-line
                        client = ConvexClient($YOUR_CONVEX_URL),
                        // highlight-next-line
                        modifier = Modifier.padding(innerPadding)
                    // highlight-next-line
                    )
                }
            }
        }
    }
    ```

  </Step>

  <Step title="Fix any missing imports">
    Fix up any missing imports (your import declarations should look something
    like this):

    ```kotlin
    import android.os.Bundle
    import androidx.activity.ComponentActivity
    import androidx.activity.compose.setContent
    import androidx.activity.enableEdgeToEdge
    import androidx.compose.foundation.layout.fillMaxSize
    import androidx.compose.foundation.layout.padding
    import androidx.compose.foundation.lazy.LazyColumn
    import androidx.compose.foundation.lazy.items
    import androidx.compose.material3.Scaffold
    import androidx.compose.material3.Text
    import androidx.compose.runtime.Composable
    import androidx.compose.runtime.LaunchedEffect
    import androidx.compose.runtime.getValue
    import androidx.compose.runtime.mutableStateOf
    import androidx.compose.runtime.remember
    import androidx.compose.runtime.setValue
    import androidx.compose.ui.Modifier
    import dev.convex.android.ConvexClient
    import kotlinx.serialization.Serializable
    ```

  </Step>
  <Step title="Run the app">
    You can also try adding, updating or deleting documents in your `tasks`
    table at `dashboard.convex.dev` - the app will update with the changes in
    real-time.

    ```
    From the IDE menu choose "Run" > "Run 'app'"
    ```

  </Step>

</StepByStep>

See the complete [Android Kotlin documentation](/client/android.md).
